﻿using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Threading;
using GermaneShanidze.Applications.Jokeri.LobbyServiceProxy;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Unity;
using GermaneShanidze.Applications.Jokeri.LobbyServiceDuplexProxy;
using System.ServiceModel;
using System.ServiceModel.Channels;
using GermaneShanidze.Applications.Jokeri.ModalWindow.Service;
using GermaneShanidze.Applications.Jokeri.Views;

namespace GermaneShanidze.Applications.Jokeri.ViewModels
{
    public class LobbyUsersViewModel : ViewModelBase
    {
        #region Reference to Container
        public IUnityContainer Container { get; private set; }
        #endregion Reference to Container

        DispatcherTimer dispatcherTimer;

        private ObservableCollection<FacebookUserInfo> activeUsers;
        public ObservableCollection<FacebookUserInfo> ActiveUsers
        {
            get { return activeUsers; }
            set
            {
                if (activeUsers != value)
                {
                    activeUsers = value;
                    OnPropertyChanged("ActiveUsers");
                }
            }
        }
        
        private bool isBusyLoading;
        public bool IsBusyLoading
        {
            get { return isBusyLoading; }
            set
            {
                if (isBusyLoading != value)
                {
                    isBusyLoading = value;
                    OnPropertyChanged("IsBusyLoading");
                }
            }
        }

        private FacebookUserInfo selectedPlayer;
        public FacebookUserInfo SelectedPlayer
        {
            get { return selectedPlayer; }
            set
            {
                if (selectedPlayer != value)
                {
                    selectedPlayer = value;
                    OnPropertyChanged("SelectedPlayer");
                }
            }
        }

        public ICommand InvitePlayerCommand { get; private set; }

        private DuplexServiceClient lobbyDuplexService;
        private CustomBinding binding = new CustomBinding(
            new PollingDuplexBindingElement(),
            new BinaryMessageEncodingBindingElement(),
            new HttpTransportBindingElement());

        // Constructor
        public LobbyUsersViewModel(IUnityContainer container)
        {
            // Container
            Container = container;

            // Bind Commands
            this.InvitePlayerCommand = new DelegateCommand<object>(this.InvitePlayer);

            // Bind DuplexServiceClient acions
            lobbyDuplexService = new DuplexServiceClient(binding, new EndpointAddress("http://localhost:53434/FileSendService.svc"));
            lobbyDuplexService.SendToClientReceived += new EventHandler<SendToClientReceivedEventArgs>(DuplexServiceSendToClientReceived);
            lobbyDuplexService.SendToServiceCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(DuplexServiceSendToServiceCompleted);

            // Start timer
            dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Interval = new TimeSpan(0, 0, 10); // 10 seconds 
            dispatcherTimer.Tick += new EventHandler(Poll_Update);
            dispatcherTimer.Start();
        }

        void Poll_Update(object sender, EventArgs e)
        {
            //Recover Singleton FacebookUserInfo object
            FacebookUserInfo fui = Container.Resolve<FacebookUserInfo>("standard");

            // Poll the service
            LobbyServiceProxy.LobbyUserServiceClient proxy = new LobbyServiceProxy.LobbyUserServiceClient();
            proxy.GetActiveUsersCompleted += new EventHandler<LobbyServiceProxy.GetActiveUsersCompletedEventArgs>(proxy_GetActiveUsersCompleted);
            proxy.GetActiveUsersAsync(fui);
            IsBusyLoading = true;
        }

        void proxy_GetActiveUsersCompleted(object sender, LobbyServiceProxy.GetActiveUsersCompletedEventArgs e)
        {
            if (e.Error == null)
                ActiveUsers = e.Result;

            IsBusyLoading = false;
        }

        private void DuplexServiceSendToClientReceived(object sender, SendToClientReceivedEventArgs e)
        {
            if (e.Error == null)
            {
                if (e.msg is ClientConnectedMessage)
                {
                    ClientConnectedMessage msg = (ClientConnectedMessage)e.msg;
                    //AddMsgToListbox(msg.Username + " has just connected.");
                    //connectedTo = msg.Username;
                    //UIState = UIState.Chat;
                }

                else if (e.msg is HostSessionServerMessage)
                {
                    HostSessionServerMessage hssm = e.msg as HostSessionServerMessage;
                    if (hssm.Failed)
                    {
                        //MessageBox.Show("Could not create session.  Please try again later or try entering a different user name.");
                        return;
                    }
                    //SessionCreated(hssm);

                }
                else if (e.msg is JoinSessionServerMessage)
                {
                    JoinSessionServerMessage jssm = e.msg as JoinSessionServerMessage;
                    if (jssm.Failed)
                    {
                        //MessageBox.Show("Failed to Connect");
                        return;
                    }
                    //SessionJoined(jssm);
                }
                else if (e.msg is FileBeginUploadMessage)
                {
                    FileBeginUploadMessage fsm = (FileBeginUploadMessage)e.msg;

                    //int sizeInKB = (int)fsm.TotalBytes / 1024;
                    //totalRevd = 0;
                    //if (MessageBox.Show(connectedTo + " would like to send you the file: " + fsm.FileName + ", Size: " + sizeInKB + " KB.  Would you like to receive this file?", "File Upload", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                    //{
                    //    bytesReceived = new List<byte>((int)fsm.TotalBytes);

                    //    fileNameReceiving = fsm.FileName;
                    //    totalFileSize = fsm.TotalBytes;
                    //    fileProgress.Value = 0;
                    //    AddMsgToListbox("File download started: " + fsm.FileName);
                    //    UIState = UIState.FileReceiving;
                    //    btnSendFile.IsEnabled = false;
                    //    tbFileStatus.Text = "Receiving File: " + fsm.FileName;
                    //}
                    //else
                    //{
                    //    fileDuplexService.SendToServiceAsync(new SendToService(new FileDenyMessage()));
                    //}
                }
                else if (e.msg is FileTransferBytesMessage)
                {
                    //if (bytesReceived == null)
                    //    return;
                    FileTransferBytesMessage fm = (FileTransferBytesMessage)e.msg;
                    //bytesReceived.AddRange(fm.Bytes);
                    //totalRevd += fm.PacketSize;
                    //double perc = ((double)totalRevd / (double)totalFileSize) * (double)100;
                    //fileProgress.Value = (int)perc;
                    //if (fm.EndFile)
                    //{
                    //    txtRecv.Text = fileNameReceiving ?? string.Empty;
                    //    UIState = UIState.FileSave;
                    //    AddMsgToListbox("File download complete, either save to disk, or click ignore to disregard file.");
                    //}
                }
                else if (e.msg is FileDenyMessage)
                {
                    //UIState = UIState.Chat;
                    //AddMsgToListbox(connectedTo + " cancelled the file transfer.");

                    //if (fileToSend != null)
                    //{
                    //    fileToSend.Close();
                    //    fileToSend = null;
                    //    btnSendFile.IsEnabled = true;
                    //}
                }
                else if (e.msg is FileReceivedMessage)
                {
                    //btnSendFile.IsEnabled = true;
                    //AddMsgToListbox(connectedTo + " finished receiving file.");
                }
                else if (e.msg is ChatMessage)
                {
                    ChatMessage msg = (ChatMessage)e.msg;
                    //AddMsgToListbox(connectedTo + "> " + msg.Message);
                }
                else if (e.msg is ClientDisconnectedMessage)
                {
                    //ClientDisconnected((ClientDisconnectedMessage)e.msg);
                }
                else if (e.msg is HostDisconnectedMessage)
                {
                    //HostSessionEnded((HostDisconnectedMessage)e.msg);
                }
                else if (e.msg is GeneralError)
                {
                    //MessageBox.Show(((GeneralError)e.msg).ErrorMessage, "Error", MessageBoxButton.OK);
                }

            }
        }

        private void DuplexServiceSendToServiceCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (e.UserState == null)
                    return;
            }
        }

        private void InvitePlayer(object obj)
        {
            var dialog = Container.Resolve<ModalDialogService>("standard");

            dialog.ShowDialog(new GameInvitationModalView(), 
                new GameInvitationModalViewModel(),
                returnedViewModelInstance =>
                {
                    if (returnedViewModelInstance.DialogResult.HasValue && returnedViewModelInstance.DialogResult.Value)
                    {
                        FacebookUserInfo fui = Container.Resolve<FacebookUserInfo>("standard");
                        JoinSessionMessage jsm = new JoinSessionMessage();
                        jsm.Username = SelectedPlayer.UserId.ToString();
                        jsm.SessionKey = fui.UserId.ToString();
                        lobbyDuplexService.SendToServiceAsync(jsm);
                    }
                });
        }

        public bool OnInvitePlayerClosed { get; set; }
    }
}
